// Package dao
// @Author zhongxc
// @Date 2024/7/3 11:08:00
// @Desc
package dao

import (
	"context"
	"errors"
	"gorm.io/gorm"
	"log"
	"time"
	"vben-admin/pkg/model"
	"vben-common/msdb"
	"vben-common/msdb/gorms"
)

type DepartmentDao struct {
	conn *gorms.GormConn
}

func NewDepartmentDao(db *msdb.MsDB) *DepartmentDao {
	return &DepartmentDao{
		conn: gorms.New(db.Conn),
	}
}

// GetDepartmentList 获取部门列表，根据部门名称和状态进行过滤。
// 参数:
//
//	ctx: 上下文对象，用于取消请求、超时等。
//	name: 部门名称，用于过滤结果，如果为空，则不根据名称过滤。
//	status: 部门状态，用于过滤结果，只返回状态匹配的部门。
//
// 返回值:
//
//	[]*model.DepartmentModel: 符合条件的部门模型列表。
//	error: 如果查询过程中出现错误，则返回错误对象；否则返回nil。
func (d *DepartmentDao) GetDepartmentList(ctx context.Context, name string, status int32) ([]*model.DepartmentModel, error) {
	// 获取数据库会话
	db := d.conn.Session(ctx)
	var deptList []*model.DepartmentModel
	// 如果部门名称不为空，则根据名称进行模糊查询
	// if name != "" {
	// 	db = db.Where("name like ?", "%"+name+"%")
	// }

	// 根据删除状态和部门状态查询符合条件的部门列表
	// 注意：这里使用了两个Where条件，分别过滤删除状态和部门状态
	err := db.Where("deleted=?", 0).Where("status = ?", status).Find(&deptList).Error
	if err != nil {
		return nil, err
	}
	return deptList, nil
}

// GetDepartmentById 根据部门ID获取部门信息。
// 该方法通过数据库查询来获取指定ID的部门详情。
// 参数:
//
//	ctx: 上下文对象，用于传递请求相关的上下文信息，如取消信号。
//	departmentId: 部门的唯一标识ID。
//
// 返回值:
//
//	*model.DepartmentModel: 查询到的部门模型，如果未找到或发生错误，则为nil。
//	error: 查询过程中可能出现的错误，如果查询成功，则为nil。
func (d *DepartmentDao) GetDepartmentById(ctx context.Context, departmentId int64) (*model.DepartmentModel, error) {
	// 获取数据库会话
	db := d.conn.Session(ctx)
	// 当部门ID不为0时，尝试查询该部门
	if departmentId != 0 {
		var dept model.DepartmentModel
		// 根据ID查询第一个匹配的部门记录
		err := db.Where("id = ?", departmentId).First(&dept).Error
		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				log.Printf("未找到部门, 部门ID: %d", departmentId)
				return nil, nil
			} else {
				// 如果查询出错，返回错误信息
				log.Printf("查询部门出错, 部门ID: %d, 错误信息: %v", departmentId, err)
				return nil, err
			}
		}
		// 如果查询成功，返回查询到的部门信息
		return &dept, nil
	}
	// 如果部门ID为0，表示没有指定的部门进行查询，返回nil
	return nil, nil
}

// GetDepartmentByName
// @Description: 根据部门名称从数据库中获取部门信息, 该方法尝试查询名称匹配的首个部门记录，并处理查询中可能出现的未找到记录的情况
// @receiver d
// @param ctx	上下文对象，用于控制请求的生命周期
// @param name	部门的名称，用于查询
// @return dept	查询到的部门模型，如果未找到，则为nil
// @return err	查询过程中可能出现的错误，如果部门未找到，则错误为nil
func (d *DepartmentDao) GetDepartmentByName(ctx context.Context, name string) (dept *model.DepartmentModel, err error) {
	// 获取数据库会话。
	db := d.conn.Session(ctx)
	// 执行查询，尝试找到名称为name的第一个部门记录。
	err = db.Where("name = ?", name).First(&dept).Error
	// 检查错误是否为记录未找到错误，如果是，则返回nil而不是错误。
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, nil
	}
	// 如果没有错误，返回查询到的部门和nil错误。
	return
}

func (d *DepartmentDao) Create(ctx context.Context, department *model.DepartmentModel) error {
	db := d.conn.Session(ctx)
	err := db.Omit(model.IgnoreDeletedAt, model.IgnoreUpdatedBy, model.IgnoreUpdatedAt).Create(department).Error
	return err
}

func (d *DepartmentDao) UpdateById(ctx context.Context, id int64, department map[string]interface{}) error {
	db := d.conn.Session(ctx)
	err := db.Model(&model.DepartmentModel{}).Where("id = ?", id).Updates(department).Error
	return err
}

func (d *DepartmentDao) DeleteById(ctx context.Context, id int64) error {
	db := d.conn.Session(ctx)
	data := map[string]interface{}{
		"deleted":    1,
		"deleted_at": time.Now(),
	}
	err := db.Model(&model.DepartmentModel{}).
		Where("id = ?", id).
		Updates(data).
		Error
	if err != nil {
		return err
	}
	return nil
}

func (d *DepartmentDao) CheckDeptHasChild(ctx context.Context, id int64) (*model.DepartmentModel, error) {
	db := d.conn.Session(ctx)
	var dept model.DepartmentModel
	err := db.Where("parent_id = ?", id).Where("deleted=?", 0).First(&dept).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		} else {
			return nil, err
		}
	}
	return &dept, nil
}

// FindNodeWithChildById 查询指定节点以及所有子节点的ID列表
func (d *DepartmentDao) FindNodeWithChildById(ctx context.Context, deptId []int64) ([]int64, error) {
	// db := d.conn.Session(ctx)

	return nil, nil
}
